MySQL面试题:主从复制binlog延迟太多怎么办

一、概述

  • 之前在网上看到有人分享面试经验:binlog复制延迟太多怎么办,对于这个问题在工作当中也是很常见的一个问题。
  • 之前分析过,MySQL基于二进制日志binlog实现的主从复制是一种异步复制,即主库对于数据库修改操作,首先记录到binlog然后在修改数据库文件。主库的复制线程读取binlog然后传输给从库,从库的复制线程接收保存为relay log,然后再由SQL线程读取relay log并在从库执行该SQL。故整个过程是存在延迟的,实现的是最终一致性。所以如果项目需要使用主从复制,则前提是从库的数据存在延迟能满足业务需求。
  • 正常来说,MySQL的主从复制是比较快的,延迟很小基本不会对应用造成影响,如果延迟太多,则首先需要分析发送延迟的原因。

二、延迟的原因与解决办法

a. 硬件资源瓶颈

由MySQL主从复制的过程分析可知,主从复制过程其实就是二进制日志读取,传输,接收,解析执行的过程,故整个过程涉及到的主要资源包括:CPU,内存,磁盘IO,网络IO。所以在发生延迟太多时,可以观察对应时刻的以上硬件资源的负载和使用情况。

b. 主库
  • 主库主要是读取binlog文件然后传输出去,所以主要可能成为性能瓶颈的就是磁盘IO,内存,网络IO。
  • 磁盘IO:如果主库所在主机上面,如果还存在其他磁盘IO繁忙的进程,如kafka进程,则可能导致主库复制线程在读取binlog时存在竞争而导致读取缓慢,所以可以使用如iostat命令来监控。
  • 内存:复制线程首先需要将binlog读取到内存,然后发送出去,故如果主库主机的内存使用太大,也会影响数据的复制,具体可以通过top,free命令来监控;
  • 网络IO:复制线程最终要通过网络将数据传输出去,故如果主库主机的网络带宽太小或者主机上存在其他需要大量消耗网络带宽的进程,则网络带宽可能成为瓶颈。具体可以通过vmstat,nethogs等查看网络带宽消耗。
c. 从库
  • 从库需要从主库接收binlog并写到relay log中,所以也存在与主库类似的问题。同时从库的SQL线程还需要读取relay log并执行对应的SQL,故除此之外,还可能由于CPU繁忙,导致SQL执行缓慢。
d. 解决方案
  • 如果发现刚好是以上硬件资源导致的性能瓶颈,则可以相应的提高硬件资源的配置或者将对应主机上面的进程根据是否存在资源竞争,分开到不同机器部署。
  • 如果硬件资源已经很好,无法通过提高硬件资源配置来解决这个问题,则可以优化应用来解决。
三、数据库是否以写操作为主:binlog日志量太大
  • 正常情况下,如果应用的写操作不是异常频繁,MySQL的binlog复制不会存在严重的延迟问题,因为binlog性能还是比较高的。但是如果是因为应用存在大量数据库写操作,导致binlog日志很大,需要从主库复制大量数据给从库,则需要考虑对应用进行拆分部署。
解决方案:分库分表
  • 针对数据库方面的拆分主要是结合分库分表来实现,即对于分库,则根据业务内聚性,拆分为几个相对独立的子服务,各个子服务使用独立的数据库分开部署,则可以将写操作分散到各个数据库,各个数据库的复制流量相对较小,从而通过分而治之的方法来降低整体的延迟。
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 拉取mysql8.0镜像 ``` docker pull mysql:8.0 ``` 2. 创建主从复制网络 ``` docker network create mysql-replication ``` 3. 创建主库容器 ``` docker run -d --name mysql-master \ -e MYSQL_ROOT_PASSWORD=123456 \ -e MYSQL_DATABASE=test \ --network mysql-replication \ mysql:8.0 \ --server-id=1 \ --log-bin='mysql-bin-1.log' \ --binlog-do-db=test \ --binlog-ignore-db=mysql \ --skip-host-cache \ --skip-name-resolve ``` 参数说明: - `--name`:容器的名称 - `-e MYSQL_ROOT_PASSWORD`:设置root用户的密码 - `-e MYSQL_DATABASE`:创建一个名为test的数据库 - `--server-id`:设置服务器唯一ID,必须唯一,从库也要设置不同的ID - `--log-bin`:开启二进制日志,并设置日志文件名 - `--binlog-do-db`:只记录指定的数据库的操作 - `--binlog-ignore-db`:忽略指定的数据库的操作 - `--skip-host-cache`:不缓存DNS查询结果 - `--skip-name-resolve`:禁用DNS反向查找功能 4. 创建从库容器 ``` docker run -d --name mysql-slave \ -e MYSQL_ROOT_PASSWORD=123456 \ -e MYSQL_DATABASE=test \ --network mysql-replication \ mysql:8.0 \ --server-id=2 \ --log-bin='mysql-bin-1.log' \ --binlog-do-db=test \ --binlog-ignore-db=mysql \ --skip-host-cache \ --skip-name-resolve \ --slave-skip-errors=all \ --slave-net-timeout=60 \ --skip-slave-start \ --master-host=mysql-master \ --master-user=root \ --master-password=123456 \ --master-port=3306 \ --master-connect-retry=60 ``` 参数说明: - `--slave-skip-errors=all`:忽略所有的错误,避免因为一些错误导致复制中断 - `--slave-net-timeout=60`:设置从库连接主库的超时时间为60秒 - `--skip-slave-start`:启动容器后不自动启动从库 - `--master-host`:指定主库的地址,这里使用了主从复制网络中主库的容器名称 - `--master-user`:指定连接主库的用户名 - `--master-password`:指定连接主库的密码 - `--master-port`:指定主库的端口 - `--master-connect-retry`:连接主库失败后重试的间隔时间 5. 开启从库 ``` docker exec -it mysql-slave mysql -uroot -p123456 -e "start slave;" ``` 6. 查看主从复制状态 ``` docker exec -it mysql-master mysql -uroot -p123456 -e "show master status;" docker exec -it mysql-slave mysql -uroot -p123456 -e "show slave status\G;" ``` 如果复制正常,Slave_IO_Running 和 Slave_SQL_Running 都为 Yes。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值